<script setup>
import { onMounted, reactive , onUnmounted, ref} from 'vue'
import { ElMessage } from 'element-plus'
import {connectApi, disconnectApi, queryStatusApi, reportGeneralEventApi} from '@/api/iotApi'
import GeneralEventReport from '@/components/GeneralEventReport.vue'
import {parseTime} from '@/utils/time'
import {QuestionFilled,ArrowDownBold,ArrowUpBold } from '@element-plus/icons-vue'
import {getRandomString} from '@/utils/random'
import { debounce } from '@/utils/common'
import AddDeviceDialog from './AddDeviceDialog.vue'
import OnlineImportDeviceDialogVue from './OnlineImportDeviceDialog.vue'

const tableContent = ref()
const data = reactive({
  //设备列表
  deviceCount: 0,
  deviceList: [],
  deviceIdList: new Set(),
  //上线开关
  online: false,
  logTable: [],
  // 启用标签
  activeTab: 'event',
  eventSelected: 'generalEvent',
  wsConnected: false,
  wsClientId: '',
  tableHeight: 300,
  // 折叠日志表格
  hideLogTable : false,
  //新增设备表单
  addDeviceDialog: false,
  // 在线导入设备表单
  onlineImportDialog: false,
  // 设备信息对话框
  deviceInfoDialog: false,
  deviceInfoData: {},
  // 监听云端服务调用
  listenService: false
})
// ws客户端id
const clientId = getRandomString(6)

//刷新设备状态任务
var intervalId;
// 支持事件列表
const eventOptions = [
	{
		value: 'generalEvent',
		label: 'generalEvent',
	  }
]

//添加设备列表
const appendDeviceList = (deviceList) => {
	if (Array.isArray(deviceList) && isValidData(deviceList)) {
		let addCount = 0
		//去重
		for(let d of deviceList) {
			let did = `${d.pk}-${d.dn}`
			if (!data.deviceIdList.has(did)) {
				data.deviceList.push(Object.assign({}, d))
				data.deviceIdList.add(did)
				addCount++
			}
		}
		if (addCount > 0) {
			ElMessage({
				message: '导入设备成功：' + addCount,
				type: 'success',
			  })
			data.deviceCount = data.deviceCount + addCount
			//缓存设备列表
			localStorage.setItem('deviceList', JSON.stringify(data.deviceList))
		} else {
			ElMessage({
			    message: '导入设备成功0台，请检查是否存在重复数据',
			    type: 'warning',
			  })
		}
		//console.log(data.deviceList)
		return addCount;
	} else {
		return -1;
	}
}

//添加设备
const addDevice = (formEl, fromData)=>{
	if (!formEl) return
	formEl.validate((valid, fields) => {
		if (valid) {
			//判断设备是否重复
			if (appendDeviceList([fromData]) > 0) {
				//关闭输入表单
				data.addDeviceDialog = false
				//清空输入
				formEl.resetFields()
			}
		} else {
		  console.log('error submit!', fields)
		}
	})
}

// 导入设备
const importDevice = (file)=>{
	if (file) {
		const reader = new FileReader();
		reader.onload = (e) => {
		  try {
			let jsonData = JSON.parse(e.target.result);
			if (appendDeviceList(jsonData) < 0) {
				ElMessage.error('加载设备失败，请检查配置')
			}
		  } catch (error) {
			ElMessage.error('解析设备配置失败:' + error.message)
		  }
		};
		reader.onerror = (error) => {
		  ElMessage.error('读取设备配置文件失败:' + error.message)
		};
		reader.readAsText(file.raw);
	}
}
// 清空设备
const removeDevice = ()=>{
	if (data.online) {
		ElMessage.error('请先将设备离线')
		return
	}
	data.deviceList = []
	localStorage.removeItem('deviceList');
	data.deviceCount = 0
	data.deviceIdList = new Set()
}

// 连接设备
const connectDevice = (value)=>{
	let dl = data.deviceList
	let reqDl
	if (value) {
		reqDl = dl.map(item => ({ pk: item.pk, dn: item.dn, ds: item.ds}));
		connectApi({wsClientId: clientId, deviceList: reqDl}).then((res)=>{
			//开启刷新任务
			setTimeout(() => {queryDeviceStatus(reqDl)}, 500)
			intervalId = setInterval(() => {queryDeviceStatus(reqDl)}, 5000)
			console.log('开启定时任务')
		}).catch((rej) => {
			data.online = false
		});
	} else {
		reqDl = dl.map(item => ({ pk: item.pk, dn: item.dn }));
		disconnectApi(reqDl)
		clearInterval(intervalId);
		console.log('关闭定时任务')
		//设置离线
		for (let i = 0; i < dl.length; i++) {
		  dl[i].on = false;
		}
	}
}

//查询设备连接状态
const queryDeviceStatus = async (value)=>{
	let ret = await queryStatusApi(value)
	if (ret.status == 200) {
		let retData = ret.data.data
		for(let i = 0; i< retData.length;i++) {
			let device = data.deviceList[i]
			if (device) {
				device.on = retData[i].on
			}
			
		}
	}
}

//上报generalEvent事件
const reportGeneralEvent = async (eventName, eventData)=>{
	let dl = data.deviceList
	if (!dl || dl.length == 0) {
		ElMessage.error('设备列表为空')
		return
	}
	if (!data.online) {
		ElMessage.error('设备离线')
		return
	}
	
	let reqDl = data.deviceList.map(item => ({ pk: item.pk, dn: item.dn, ds: item.ds, merchantId: item.merchantId, merchantName: item.merchantName,
	 storeId: item.storeId, storeName: item.storeName, productName: item.productName, cgid: item.cgid, deviceAlias: item.deviceAlias, millisecond: Date.now()}));
	reportGeneralEventApi(reqDl, eventName, eventData, data.wsClientId)
	//data.logTable.unshift({dn:'12312'})
}

const handleWebSocketMessage = (event)=>{
	const message = JSON.parse(event.data);
	//console.log(message)
	if (message.time != null) {
		message.time = parseTime(message.time)
	}
	// 是否监听云端服务调用
	if (message.action == 'generalService called' && !data.listenService) {
		return
	}
	//首位添加日志
	data.logTable.unshift(message)
	//只保留20条
	if (data.logTable.length > 20) {
		data.logTable.pop()
	}
}

//清理日志
const clearLog = ()=> {
	data.logTable = []
}
//服务器日志websockt
var websocket

//断开websocket
const disconnectWs = ()=> {
	if (websocket) {
	  websocket.close()
	}
}

//连接websocket
const connectWs = ()=> {
	websocket = new WebSocket('ws://localhost:3002/' + clientId);
	websocket.onmessage = handleWebSocketMessage;
	// 连接成功
	websocket.onopen = () => {
	  data.wsConnected = true;
	  data.wsClientId = clientId;
	  console.log('WebSocket 连接成功');
	};

	// 连接关闭
	websocket.onclose = () => {
	  data.wsConnected = false;
	  console.log('WebSocket 连接已关闭');
	};

	// 发生错误
	websocket.onerror = (error) => {
	  data.wsConnected = false;
	  console.error('WebSocket 发生错误:', error);
	  ElMessage.error('连接失败')
	};
}

//在线导入设备
const onlineImport = (fromData)=>{
	if(appendDeviceList(fromData) >= 0) {
		data.onlineImportDialog = false
	}
}

//查看设备信息
const showDeviceInfo = (device)=>{
	data.deviceInfoData = device
	data.deviceInfoDialog = true
}


const hideLogTable = (isHide)=>{
	data.hideLogTable = isHide
}

const isValidData = (data) => {
	return data.every(item => 
	item.pk && item.dn && item.ds
	);
}

// 计算表格高度
const resizeTable = () => {
	data.tableHeight = tableContent.value.offsetHeight - 50
}

onMounted(() => {
	//取出缓存设备
	const storedDeviceList = localStorage.getItem('deviceList');
	data.deviceList = storedDeviceList ? JSON.parse(storedDeviceList) : [];
	data.deviceCount = data.deviceList.length
	data.deviceIdList = new Set(data.deviceList.map(item => item.pk + '-' + item.dn));
	
	//connectWs()
	//console.log("tableContent h:" + tableContent.value.offsetHeight)
	resizeTable()
	// 计算代码块高度
	const debouncedResize = debounce(resizeTable, 200);
	// 添加 resize 事件监听器
	window.addEventListener('resize', debouncedResize);
})

onUnmounted(() => {
   disconnectWs()
   if (data.online) {
	  connectDevice(false) 
   }
})
</script>

<template>
	<div class="h-full w-full">
		<div class="flex flex-row h-full">
			<div class="flex-col h-full floverflow-y-auto px-3 py-3 border rounded-l-md">
				<div class="flex flex-row">
					<el-text class="flex-shrink-0">设备：{{data.deviceCount}}</el-text>
					<div class="flex-1 text-right">
						<el-switch class="ml-4 mr-4" v-model="data.online" inline-prompt active-text="在线"
							inactive-text="离线" @change="connectDevice" />
					</div>
				</div>
				<div class="flex flex-row">
					<el-button type="primary" @click="data.addDeviceDialog = true">新增</el-button>
					<el-upload class="inline ml-4" :auto-upload="false" :show-file-list="false"
						:on-change="importDevice">
						<el-button type="primary">批量导入</el-button>
					</el-upload>
					<el-popconfirm title="确认清空设备列表?" @confirm="removeDevice">
						<template #reference>
							<el-button class="ml-4" type="primary">清空</el-button>
						</template>
					</el-popconfirm>
				</div>
				<div class="mt-2">
					<el-button type="primary" @click="data.onlineImportDialog = true">在线导入</el-button>
				</div>
				<el-divider content-position="center">设备列表</el-divider>
				<div v-if="data.deviceList && data.deviceList.length > 0" v-for="item in data.deviceList" class="flex flex-row items-center py-4 px-2 border border-slate-100 hover:shadow-md hover:translate-x-2 duration-300" @click="showDeviceInfo(item)">
					<el-text class="flex-1">{{item.dn}}</el-text>
					<div class="rounded-full w-4 h-4 border"
						:class="{ 'bg-green-300': item.on,  'bg-gray-300': !item.on }"></div>
				</div>
				<div v-else><el-empty description="无数据" :image-size="100"/></div>
			</div>
			<div class="flex  flex-col flex-1 h-full px-5 py-3 border rounded-r-md" style="width: 0;">
				<!-- 功能切换 -->
				<div class="flex-1 py-2">
					<el-tabs v-model="data.activeTab" class="h-full">
						<el-tab-pane label="事件上报" name="event" class="h-full">
							<GeneralEventReport @reportEvent="reportGeneralEvent" />
						</el-tab-pane>
						<el-tab-pane label="属性上报" name="propertry" class="h-full">
							暂未支持，有空再搞
						</el-tab-pane>
						<el-tab-pane label="服务调用" name="service" class="h-full">
							监听云端服务调用：
							<el-switch
							    v-model="data.listenService"
							    inline-prompt
							    active-text="开启"
							    inactive-text="关闭"
							  />
						</el-tab-pane>
					</el-tabs>
				</div>
				<!-- 设备日志 -->
				<div class="w-full border-t py-2" ref="tableContent" :class="{'flex-1' : !data.hideLogTable}">
					<div class="flex flex-row items-center">
						<el-text>设备日志</el-text>
						<div class="rounded-full w-4 h-4 ml-2 border"
							:class="{ 'bg-green-300': data.wsConnected,  'bg-gray-300': !data.wsConnected }"></div>
						<el-tooltip class="box-item" effect="light" content="必须在线状态才会收到日志, 只显示最近20条"
							placement="top"><el-icon class="ml-2">
								<QuestionFilled />
							</el-icon>
						</el-tooltip>
						<el-button class="ml-2" @click="clearLog">清空</el-button>
						<el-button class="ml-2" v-if="data.wsConnected" @click="disconnectWs">断开连接</el-button>
						<el-button class="ml-2" v-else @click="connectWs">重新连接</el-button>
						<div class="flex flex-1 justify-end">
							<el-button v-if="data.hideLogTable" :icon="ArrowUpBold" circle
								@click="hideLogTable(false)" />
							<el-button v-else :icon="ArrowDownBold" circle @click="hideLogTable(true)" />
						</div>
					</div>
					<div class="table-content" v-show="!data.hideLogTable">
						<el-table :data="data.logTable" :max-height="data.tableHeight" >
							<el-table-column prop="dn" label="设备名称" width="200" />
							<el-table-column prop="time" label="时间" width="200" />
							<el-table-column prop="action" label="动作" />
							<el-table-column prop="message" label="信息" />
						</el-table>
					</div>

				</div>
			</div>

		</div>
	</div>
	
	<el-dialog v-model="data.deviceInfoDialog" title="设备信息" width="1200">
		<el-descriptions :column="1" border>
			<el-descriptions-item label="商家" >{{data.deviceInfoData.merchantName}}</el-descriptions-item>
			<el-descriptions-item label="门店">{{data.deviceInfoData.storeName}}</el-descriptions-item>
			<el-descriptions-item label="产品名称">{{data.deviceInfoData.productName}}</el-descriptions-item>
			<el-descriptions-item label="ProductKey">{{data.deviceInfoData.pk}}</el-descriptions-item>
			<el-descriptions-item label="DeviceName">{{data.deviceInfoData.dn}}</el-descriptions-item>
			<el-descriptions-item label="DeviceSecret">{{data.deviceInfoData.ds}}</el-descriptions-item>
			<el-descriptions-item label="cgid">{{data.deviceInfoData.cgid}}</el-descriptions-item>
			<el-descriptions-item label="设备别名">{{data.deviceInfoData.deviceAlias}}</el-descriptions-item>
		</el-descriptions>
	</el-dialog>
	
	<!-- 新增设备 -->
	<AddDeviceDialog :show="data.addDeviceDialog" @close="data.addDeviceDialog=false" @submit="addDevice"></AddDeviceDialog>

	<!-- 在线导入设备表单 -->
	<OnlineImportDeviceDialogVue :show="data.onlineImportDialog" @close="data.onlineImportDialog=false" @submit="onlineImport"></OnlineImportDeviceDialogVue>
</template>

<style>
.el-transfer-panel{
	width: 400px!important;
}
</style>